package com.swak.paxos.state;

import com.swak.utils.StringUtils;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

@Getter
@Setter
@Accessors(chain = true)
@Data
public class BallotNumber {
	private long proposalID = 0;
	private String nodeID = StringUtils.EMPTY;

	public BallotNumber(long proposalID) {
		this.proposalID = proposalID;
	}

	public BallotNumber(long proposalID, String nodeID) {
		this.proposalID = proposalID;
		this.nodeID = nodeID;
	}

	/**
	 * prepare 阶段：
	 * 
	 * Promise 只能接受大于 Promise 的 编号；
	 * 
	 * 如果是本节点： 则可以接受
	 * 如果相等则只能是本节点，否则必须大于 Promise
	 * 
	 * 也就是： Promise 不在接受比 Promise 小的值（如果等于必须是本节点）
	 * @param other
	 * @return
	 */
	public boolean gt(BallotNumber other) {

		// 开启这段代码主要是： 应对 Timeout 时重新发起 prepare
		if (this.proposalID == other.getProposalID()) {
			return this.nodeID.equals(other.getNodeID());
		}

		// 默认走这个逻辑即可
		return this.proposalID > other.getProposalID();
	}

	/**
	 * accept 阶段：
	 * 
	 * Promise 不再接受 不小于  Promise 的 编号；
	 * 
	 * 如果是本节点： 则可以接受
	 * 如果相等则只能是本节点，否则必须大于 Promise
	 * 
	 * 也就是： Promise 不在接受比 Promise 小的值（如果等于必须是本节点）
	 * @param other
	 * @return
	 */
	public boolean ge(BallotNumber other) {
		return this.proposalID >= other.getProposalID();
	}

	public void reset() {
		this.proposalID = 0;
		this.nodeID = StringUtils.EMPTY;
	}

	public boolean isNull() {
		return this.proposalID == 0;
	}
}
